/*
 * MPEGTS.h
 *
 *  Created on: Mar 28, 2013
 *      Author: root
 */

#ifndef MPEGTS_H_
#define MPEGTS_H_

#include "StreamBuffer.h"
#include "StreamFormat.h"

/*mpegts define*/
#define TS_FEC_PACKET_SIZE 204
#define TS_DVHS_PACKET_SIZE 192
#define TS_PACKET_SIZE 188
#define TS_MAX_PACKET_SIZE 204

#define NB_PID_MAX 8192
#define MAX_SECTION_SIZE 4096

/* pids */
#define PAT_PID                 0x0000
#define SDT_PID                 0x0011

/* table ids */
#define PAT_TID   0x00
#define PMT_TID   0x02
#define SDT_TID   0x42

#define STREAM_TYPE_VIDEO_MPEG1     0x01
#define STREAM_TYPE_VIDEO_MPEG2     0x02
#define STREAM_TYPE_AUDIO_MPEG1     0x03
#define STREAM_TYPE_AUDIO_MPEG2     0x04
#define STREAM_TYPE_PRIVATE_SECTION 0x05
#define STREAM_TYPE_PRIVATE_DATA    0x06
#define STREAM_TYPE_AUDIO_AAC       0x0f
#define STREAM_TYPE_VIDEO_MPEG4     0x10
#define STREAM_TYPE_VIDEO_H264      0x1b
#define STREAM_TYPE_VIDEO_VC1       0xea
#define STREAM_TYPE_VIDEO_DIRAC     0xd1

#define STREAM_TYPE_AUDIO_AC3       0x81
#define STREAM_TYPE_AUDIO_DTS       0x8a

#define MAX_PIDS_PER_PROGRAM 64
struct TSProgram
{
    unsigned int id; //program id/service id
    unsigned int nb_pids;
    unsigned int pids[MAX_PIDS_PER_PROGRAM];
};

/*m3u8 define*/
#define DEFAULD_PKT_COUNT 3
#define DEFAULD_LIST_COUNT 6
#define DEFAULD_CLIP_DURATION 10
/*ts clip info*/
struct Clip_Info
{
	uint64_t start_seq;/*start index*/
	uint64_t start_offset;/*start index offset*/
	uint64_t start_pts;/*start pts*/

	uint64_t end_seq;/*end index*/
	uint64_t end_offset;/*end index offset*/
	uint64_t end_pts;/*start pts*/

	uint64_t clip_length;/*clip data length*/
	uint16_t clip_duration;/*clip duration*/
};


/*ts context*/
struct TSContext
{
	AVPacket *header;
	AVPacket *tail;
	uint64_t current_pkt_index;

	/*m3u8 data*/
	uint16_t pkt_count;
	uint16_t list_count;
	uint16_t max_clip_duration;
	Clip_Info cliplist[DEFAULD_LIST_COUNT*5];
	uint16_t  clipindex;
	uint16_t  count_index;
	uint64_t  cliplist_index;

	/*ts info*/
	uint16_t raw_packet_size;
	uint32_t last_time_stamp;
	uint16_t pmt_pid;
	uint16_t fVideo_PID;
	uint8_t  fIsH264;
	uint16_t fAudio_PID;

	uint8_t buf[TS_MAX_PACKET_SIZE];
	size_t buf_len;

	uint8_t pat[2*TS_MAX_PACKET_SIZE];
	size_t pat_len;

	TSContext()
	{
		this->header = NULL;
		this->tail = this->header;
		this->current_pkt_index = 0;

		this->pkt_count = DEFAULD_PKT_COUNT;
		this->list_count = DEFAULD_LIST_COUNT;
		this->max_clip_duration = DEFAULD_CLIP_DURATION;
		memset(this->cliplist,NULL,sizeof(this->cliplist));
		this->clipindex = 0;
		this->count_index = 0;
		this->cliplist_index = 0;

		this->raw_packet_size = 0;
		this->last_time_stamp = 0;
		this->pmt_pid = 0;
		this->fVideo_PID = 0;
		this->fIsH264 = 0;
		this->fAudio_PID = 0;


		memset(this->buf,0,TS_MAX_PACKET_SIZE);
		this->buf_len = 0;
		memset(this->pat,0,2*TS_MAX_PACKET_SIZE);
		this->pat_len = 0;
	}
};

/**
 *MPEGTS class
 */
class MPEGTS {
public:
	MPEGTS();
	virtual ~MPEGTS();

	/*
	*get ts pakcet size
	*/
	static int analyze(const uint8_t *buf, int size, int packet_size, int *index);
	/*
	*autodetect fec presence. Must have at least 1024 bytes
	*/
	static int get_packet_size(const uint8_t *buf, int size);
	/*
	analyze pmt table
	*/
	static void analyzePMT(unsigned char* pkt, unsigned size,uint16_t &fVideo_PID ,uint8_t &fIsH264,uint16_t &fAudio_PID);
	/*
	*check pes is video key frame
	*/
	static uint16_t check_pes_video_keyframe(TSContext *c,uint8_t * data,uint64_t data_len);
	/*
	*get pes pts and dts
	*/
	static void get_pes_pts(TSContext *c,AVPacket * pkt);

	/*
	*get pes pts
	*return pts
	*/
	static uint32_t get_pes_pts(TSContext *c,uint8_t * tspkt, size_t size);
};

#endif /* MPEGTS_H_ */
